package com.chagee.store.operation.server.event.service;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chagee.store.operation.api.bo.SettlementExtJsonBO;
import com.chagee.store.operation.api.enums.*;
import com.chagee.store.operation.api.request.*;
import com.chagee.store.operation.common.constant.CommonConstant;
import com.chagee.store.operation.common.exception.BizErrorCode;
import com.chagee.store.operation.common.exception.BizException;
import com.chagee.store.operation.server.entity.StoreSettlementDO;
import com.chagee.store.operation.server.event.dao.StoreSettlementMapper;
import com.chagee.store.operation.server.utils.DateUtil;
import com.chagee.storeManagement.api.event.enums.StoreCategoryEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class StoreSettlementBaseService extends ServiceImpl<StoreSettlementMapper, StoreSettlementDO> {

	@Resource
	private StoreSettlementMapper storeSettlementMapper;

	private final SimpleDateFormat format = new SimpleDateFormat(CommonConstant.FORMAT);

	public Page<StoreSettlementDO> querySettlementPage(Page<StoreSettlementDO> page, SettlementRequest request) {

		return baseMapper.querySettlementPage(page, request);
	}

	public List<StoreSettlementDO> selectBySettlementNo(String settlementNo) {
		LambdaQueryWrapper<StoreSettlementDO> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper
			.eq(StringUtils.isNotBlank(settlementNo), StoreSettlementDO::getSettlementNo, settlementNo)
			.eq(StoreSettlementDO::getDeleteFlag, NumberUtils.INTEGER_ZERO);
		return this.list(queryWrapper);
	}

	public void updateStoreSettlement(UpdateStoreAreaRequest request) {
		this.update(lambdaUpdate().eq(StoreSettlementDO::getId, request.getId())
			.set(StringUtils.isNotEmpty(request.getStoreArea()), StoreSettlementDO::getStoreArea, request.getStoreArea())
			.set(ObjectUtils.isNotEmpty(request.getStoreLineNum()), StoreSettlementDO::getStoreLineNum, request.getStoreLineNum())
			.getWrapper());
	}

	public void updateDeleteStoreSettlement(List<StoreSettlementDO> list) {
		for (StoreSettlementDO storeSettlementDO : list) {
			if (SettlementStatusEnum.WAIT_ISSUED.getType().equals(storeSettlementDO.getDocumentStatus())) {
				this.update(lambdaUpdate().eq(StoreSettlementDO::getId, storeSettlementDO.getId())
					.set(StoreSettlementDO::getDeleteFlag, NumberUtils.INTEGER_ONE)
					.getWrapper());
			}
		}
	}

	public StoreSettlementDO querySettlement(String settlementNo) {
		if (StringUtils.isBlank(settlementNo)) {
			throw new BizException(BizErrorCode.ORDER_NOT_EXIST);
		}
		LambdaQueryWrapper<StoreSettlementDO> wrapper = new LambdaQueryWrapper<>();
		wrapper.eq(StringUtils.isNotBlank(settlementNo), StoreSettlementDO::getSettlementNo, settlementNo);
		wrapper.eq(StoreSettlementDO::getDeleteFlag, CommonConstant.NOT_DELETE_FLAG);
		wrapper.last(CommonConstant.LIMIT_ONE_SQL);
		return baseMapper.selectOne(wrapper);
	}

	public List<StoreSettlementDO> batchSelectSettlement(List<String> settlementNo) {
		LambdaQueryWrapper<StoreSettlementDO> wrapper = new LambdaQueryWrapper<>();
		wrapper.in(CollectionUtil.isNotEmpty(settlementNo), StoreSettlementDO::getSettlementNo, settlementNo);
		wrapper.in(StoreSettlementDO::getPushFinanceStatus, Arrays.asList(PushFinanceStatusEnum.NOT_PUSH.getType(),PushFinanceStatusEnum.FAILURE.getType()));
		wrapper.eq(StoreSettlementDO::getDeleteFlag, CommonConstant.NOT_DELETE_FLAG);
		return this.list(wrapper);
	}

	public void updateSettlement(StoreSettlementDO storeSettlementDO) {
		this.update(lambdaUpdate().eq(StoreSettlementDO::getSettlementNo, storeSettlementDO.getSettlementNo())
			.set(ObjectUtils.isNotEmpty(storeSettlementDO.getAdjustMoney()), StoreSettlementDO::getAdjustMoney, storeSettlementDO.getAdjustMoney())
			.set(StringUtils.isNotBlank(storeSettlementDO.getExtra()), StoreSettlementDO::getExtra, storeSettlementDO.getExtra())
			.set(ObjectUtils.isNotEmpty(storeSettlementDO.getPayMoney()), StoreSettlementDO::getPayMoney, storeSettlementDO.getPayMoney())
			.set(StringUtils.isNotBlank(storeSettlementDO.getDocumentStatus()), StoreSettlementDO::getDocumentStatus, storeSettlementDO.getDocumentStatus())
			.getWrapper());
	}

	public void updateSettlementInvoice(StoreSettlementDO storeSettlementDO) {
		this.update(lambdaUpdate().eq(StoreSettlementDO::getSettlementNo, storeSettlementDO.getSettlementNo())
			.set(StringUtils.isNotBlank(storeSettlementDO.getDocumentStatus()), StoreSettlementDO::getDocumentStatus, storeSettlementDO.getDocumentStatus())
			.set(Objects.nonNull(storeSettlementDO.getWaitPayTime()), StoreSettlementDO::getWaitPayTime, storeSettlementDO.getWaitPayTime())
			.set(StringUtils.isNotBlank(storeSettlementDO.getInvoice()), StoreSettlementDO::getInvoice, storeSettlementDO.getInvoice())
			.set(StringUtils.isNotBlank(storeSettlementDO.getPushFinanceStatus()), StoreSettlementDO::getPushFinanceStatus, storeSettlementDO.getPushFinanceStatus())
			.getWrapper());
	}

	public List<StoreSettlementDO> selectSettlements(Long id) {
		LambdaQueryChainWrapper<StoreSettlementDO> storeQuery = lambdaQuery();
		storeQuery.in(StoreSettlementDO::getDocumentStatus, Arrays.asList(SettlementStatusEnum.WAIT_PAY.getType(),SettlementStatusEnum.COMPLETE.getType()))
			.in(StoreSettlementDO::getPushFinanceStatus, Arrays.asList(PushFinanceStatusEnum.NOT_PUSH.getType(),PushFinanceStatusEnum.FAILURE.getType()))
			.eq(StoreSettlementDO::getDeleteFlag, NumberUtils.INTEGER_ZERO)
			.gt(StoreSettlementDO::getId, id)
			.orderByAsc(StoreSettlementDO::getId)
			.last(CommonConstant.LIMIT_SIZE_SQL);
		return baseMapper.selectList(storeQuery.getWrapper());
	}

	public void updateSettlement(String settlementNo, String pushFinanceStatus) {
		this.update(lambdaUpdate().eq(StoreSettlementDO::getSettlementNo, settlementNo)
			.set(StringUtils.isNotBlank(pushFinanceStatus), StoreSettlementDO::getPushFinanceStatus, pushFinanceStatus)
			.eq(StoreSettlementDO::getDeleteFlag, NumberUtils.INTEGER_ZERO)
			.getWrapper());
	}

	public List<StoreSettlementDO> selectNotPushOrders() {
		return baseMapper.selectNotPushOrders();
	}

	public List<StoreSettlementDO> batchQuerySettlement(List<String> settlementNos) {
		LambdaQueryWrapper<StoreSettlementDO> wrapper = new LambdaQueryWrapper<>();
		wrapper.in(CollectionUtil.isNotEmpty(settlementNos), StoreSettlementDO::getSettlementNo, settlementNos);
		wrapper.eq(StoreSettlementDO::getDeleteFlag, CommonConstant.NOT_DELETE_FLAG);
		return this.list(wrapper);
	}

	public void update(String documentStatus, String extra, StoreSettlementDO storeSettlementDO) {
		this.update(
			lambdaUpdate().eq(StoreSettlementDO::getSettlementNo, storeSettlementDO.getSettlementNo())
				.set(StringUtils.isNotBlank(documentStatus), StoreSettlementDO::getDocumentStatus, documentStatus)
				.set(StringUtils.isNotBlank(extra), StoreSettlementDO::getExtra, extra)
				.set(Objects.nonNull(storeSettlementDO.getWaitPayTime()), StoreSettlementDO::getWaitPayTime, storeSettlementDO.getWaitPayTime())
				.set(StringUtils.isNotBlank(storeSettlementDO.getPushInvoiceFlag()), StoreSettlementDO::getPushInvoiceFlag, storeSettlementDO.getPushInvoiceFlag())
				.set(StoreSettlementDO::getUpdateTime, new Date())
				.getWrapper());
	}

	public List<StoreSettlementDO> queryWaitPaySettlement(Long id, LocalDateTime cutoffTime) {
		LambdaQueryChainWrapper<StoreSettlementDO> wrapper = lambdaQuery();

		wrapper.eq(StoreSettlementDO::getDocumentStatus, SettlementStatusEnum.WAIT_PAY.getType())
			.eq(StoreSettlementDO::getStoreCategory, StoreCategoryEnum.JM.getType())
			.lt(StoreSettlementDO::getWaitPayTime, cutoffTime)
			.eq(StoreSettlementDO::getDeleteFlag, NumberUtils.INTEGER_ZERO)
			.gt(StoreSettlementDO::getId, id)
			.orderByAsc(StoreSettlementDO::getId)
			.last(CommonConstant.LIMIT_SIZE_SQL);
		return baseMapper.selectList(wrapper.getWrapper());
	}

	public List<StoreSettlementDO> selectSettlement(String storeNo, Date lastMonth) {
		LambdaQueryWrapper<StoreSettlementDO> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(StoreSettlementDO::getStoreNo, storeNo);
		queryWrapper.eq(StoreSettlementDO::getSettlementCycle, lastMonth);
		queryWrapper.eq(StoreSettlementDO::getDeleteFlag, NumberUtils.INTEGER_ZERO);
		return baseMapper.selectList(queryWrapper);
	}

	public List<StoreSettlementDO> querySettlements(Long id) {
		LambdaQueryChainWrapper<StoreSettlementDO> storeQuery = lambdaQuery();
		storeQuery.eq(StoreSettlementDO::getDeleteFlag, NumberUtils.INTEGER_ZERO)
			.gt(StoreSettlementDO::getId, id)
			.orderByAsc(StoreSettlementDO::getId)
			.last(CommonConstant.LIMIT_SIZE_SQL);
		return baseMapper.selectList(storeQuery.getWrapper());
	}

	public void updatePayInfo(String settlementNo, String paymentNo, String payType, String extJsonBO) {
		this.update(
			lambdaUpdate().eq(StoreSettlementDO::getSettlementNo, settlementNo)
				.set(StringUtils.isNotBlank(paymentNo), StoreSettlementDO::getPaymentNo, paymentNo)
				.set(StringUtils.isNotBlank(payType), StoreSettlementDO::getPayType, payType)
				.set(StringUtils.isNotBlank(extJsonBO), StoreSettlementDO::getExtra, extJsonBO)
				.set(StoreSettlementDO::getUpdateTime, new Date())
				.getWrapper());
	}

	public List<StoreSettlementDO> querySettlementsByPayNo(Long id) {
		LambdaQueryChainWrapper<StoreSettlementDO> storeQuery = lambdaQuery();
		storeQuery.eq(StoreSettlementDO::getDeleteFlag, NumberUtils.INTEGER_ZERO)
			.isNotNull(StoreSettlementDO::getPaymentNo)
			.isNull(StoreSettlementDO::getPayType)
			.gt(StoreSettlementDO::getId, id)
			.orderByAsc(StoreSettlementDO::getId)
			.last(CommonConstant.LIMIT_SIZE_SQL);
		return baseMapper.selectList(storeQuery.getWrapper());
	}

}
